#!/usr/bin/env python3

# Copyright (c) 2005-2014 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.


import os
import mrget
import shutil
import subprocess
from datetime import datetime
from .._util import Util
from .._handy import Handy
from .._handy import ElementMapType2
from .._datasrc import DataSourceBase


class DataSource(DataSourceBase):

    def __init__(self, tmp_dir):
        self._cacheDir = "/var/cache/librungame-repacks"
        self._tmpDir = tmp_dir

    @property
    def name(self):
        return "librungame-repacks"

    @property
    def description(self):
        return "Game Repacks for librungame"

    @property
    def homepage(self):
        return ""

    @property
    def supported_etypes(self):
        return ["game"]

    @property
    def supported_dir_types(self):
        return ["system", "user"]

    def get_priority(self, etype):
        assert etype == "game"
        return 9000

    def map_element(self, etype, esource, eindex):
        assert etype == "game"
        return _idMap.map_element(esource, eindex)

    def map_element_reverse(self, etype, eindex):
        assert etype == "game"
        return _idMap.map_element_reverse(eindex)

    def retrieve_sync_data_last_update_time(self, etype):
        assert etype == "game"
        return datetime.min

    def update_sync_data(self, etype, db_conn):
        assert etype == "game"

        url = mrget.target_urls("mirror://librungame-repacks", protocols=["http", "https"], max_count=3)[0]
        with Util.mountHttpDir(url, parentDir=self._datasrc._tmpDir) as mntDir:
            with db_conn:
                Handy.dbSyncDataDelete(db_conn, "main", self.name)
                for fn in os.listdir(mntDir):
                    db_conn.execute('''
                        INSERT INTO main.element_part (esource, eindex, pname) VALUES (%s, %s, %s);
                    ''', (self.name, fn, "main", ))

    def get_element_part_url(self, etype, eindex, pname):
        assert etype == "game"

        if pname == "main":
            url = os.path.join("mirror://librungame-repacks", eindex, eindex + ".7z")
            url = mrget.target_urls(url, protocols=["http", "https"], max_count=3)[0]
            return url
        else:
            return None

    def test_element_part_url(self, etype, eindex, pname):
        assert False

    def is_element_part_cache_update_needed(self, etype, eindex, pname):
        assert etype == "game"
        assert pname == "main"

        gameFullfn = os.path.join(self._cacheDir, eindex + ".7z")
        return os.path.exists(gameFullfn)

    def get_element_part_cache_last_update_time(self, etype, eindex, pname):
        assert etype == "game"
        assert pname == "main"

        gameFullfn = os.path.join(self._cacheDir, eindex + ".7z")
        if os.path.exists(gameFullfn):
            return datetime.fromtimestamp(os.getmtime(gameFullfn))
        else:
            return None

    def get_element_part_cache_local_path(self, etype, eindex, pname):
        assert etype == "game"
        assert pname == "main"

        gameFullfn = os.path.join(self._cacheDir, eindex + ".7z")
        if os.path.exists(gameFullfn):
            return gameFullfn
        else:
            return None

    def cache_element_part(self, etype, eindex, pname, cache_time):
        assert etype == "game"
        assert pname == "main"

        url = mrget.target_urls("mirror://librungame-repacks", protocols=["http", "https"], max_count=3)[0]

        # use tmpDir to make sure the update operation is atomic
        tmpDir = os.path.join(self._cacheDir, ".update")
        Util.forceMakeEmptyDir(tmpDir)

        gameFile = os.path.join(tmpDir, eindex + ".7z")
        subprocess.check_call(["wget", "-q", "-O", gameFile, os.path.join(url, eindex, eindex + ".7z")])

        dstGameFile = os.path.join(self._cacheDir, eindex + ".7z")
        shutil.move(gameFile, dstGameFile)

        os.rmdir(tmpDir)

    def uncache_element_part(self, etype, eindex, pname):
        assert etype == "game"
        assert pname == "main"

        gameFullfn = os.path.join(self._cacheDir, eindex + ".7z")
        Util.forceDelete(gameFullfn)

    def clean(self, etype, all_cache=False):
        assert etype == "game"

        if not all_cache:
            # FIXME: how to find redundant files?
            pass
        else:
            Util.forceDelete(self._cacheDir)


_idMap = ElementMapType2({
    ("igdb", "ah-64-apache-air-assault")         : "ah-64-apache-air-assault",
    ("igdb", "beach-head-2002")                  : "beachhead2002",
    ("igdb", "call-of-duty")                     : "call-of-duty",
    ("igdb", "call-of-duty-2")                   : "call-of-duty2",
    ("igdb", "dcs-world")                        : "dcs-world",
    ("igdb", "grand-theft-auto-iii")             : "gta3",
    ("igdb", "grand-theft-auto-san-andreas")     : "gta3-san-andreas",
    ("igdb", "grand-theft-auto-vice-city")       : "gta3-vice-city",
    ("igdb", "the-need-for-speed")               : "need-for-speed",
    ("igdb", "need-for-speed-ii")                : "need-for-speed2",
    ("igdb", "need-for-speed-iii-hot-pursuit")   : "need-for-speed3",
    ("igdb", "need-for-speed-high-stakes")       : "need-for-speed4",
    ("igdb", "need-for-speed-porsche-unleashed") : "need-for-speed5",
    ("igdb", "need-for-speed-hot-pursuit-2")     : "need-for-speed6",
    ("igdb", "need-for-speed-underground-2")     : "need-for-speed8",
    ("igdb", "need-for-speed-most-wanted")       : "need-for-speed9",
    ("igdb", "need-for-speed-carbon")            : "need-for-speed10",
    ("igdb", "neighbours-from-hell--1")          : "neighbours-from-hell",
    ("igdb", "plants-vs-zombies-goty-edition")   : "plants-vs-zombies",             # there's a plants-vs-zombies in igdb
    ("igdb", "starcraft")                        : "starcraft",
})
